package com.qipay.api.redirect.controller.v1;

import com.qipay.api.BaseController;
import com.qipay.baas.model.ChannelType;
import com.qipay.baas.model.Cp;
import com.qipay.baas.model.Order;
import com.qipay.channelType.ChannelTypeService;
import com.qipay.cp.CpService;
import com.qipay.order.config.OrderStateEnum;
import com.qipay.order.service.OrderService;
import com.qipay.pay.FourPayService;
import com.qipay.pay.entity.CpPayAlipayWapRequest;
import com.qipay.scalar.type.ApiStatusEnum;
import com.qipay.security.sign.service.SignService;
import com.qipay.utils.ResultUtils;
import com.qipay.utils.XmlUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.util.Assert;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.math.BigDecimal;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;

@RestController
@RequestMapping("/redirect/v1/conn")
public class RedirectController extends BaseController {

    protected final Logger logger = LoggerFactory.getLogger(getClass());

    @Autowired
    CpService cpService;

    @Autowired
    SignService signService;
    @Autowired
    ChannelTypeService channelTypeService;

    @Autowired
    FourPayService fourPayService;

    @Autowired
    OrderService orderService;

    @Value("${api.response.sign.name}")
    private String sigKey;
    @Value("${api.test.mchId}")
    private String mchId;
    @Value("${api.test.secret}")
    private String secret;

    /**
     * 包括原生的支付宝在内的，组装form页面直接通过表单提交到通道方
     * @param request
     * @param mchId
     * @param tradeNo
     * @param sign
     * @param response
     * @return
     * @throws Exception
     */
    @RequestMapping(value = "/formPay", method = RequestMethod.GET)
    private ModelAndView formPay(
            HttpServletRequest request,
            @RequestParam("mch_id") String mchId,
            @RequestParam("trade_no") String tradeNo,
            @RequestParam("type") String type,
            @RequestParam("sign") String sign,
            HttpServletResponse response
    ) throws Exception {
        Assert.notNull(mchId, "请输入商户ID");
        Assert.notNull(tradeNo, "请输入平台交易流水");
        Assert.notNull(sign, "请输入签名");

        Cp cp = cpService.getOneByAppId(mchId);
        Assert.notNull(cp, "错误的商户ID");

        Map<String, Object> params = new HashMap<>();
        params.put("mch_id", mchId);
        params.put("trade_no", tradeNo);
        params.put("type", type);
        params.put("sign", sign);
        String fromSig = params.get(sigKey).toString();
        String mySig = signService.getSign(params, cp.getSecretId(), sigKey);
        Assert.isTrue(StringUtils.equals(fromSig, mySig), "签名错误");

        Order order = orderService.getByTradeNo(tradeNo);
        Assert.notNull(order, "查询不到该订单");
        Assert.isTrue(mchId.equals(order.getCpId().toString()), "输入的商户号与订单信息不一致");
        //这里订单状态，只有经过excutor之后才是“等待支付”，之前还是“未支付”状态
        Assert.isTrue(Objects.equals(order.getState(), OrderStateEnum.NOTPAY.getType()),
                ResultUtils.buildErrorMsg(ApiStatusEnum.ARGUMENT_ERR, "错误的订单信息"));

        Map<String, Object> payInfoMap = fourPayService.wapPay(order.getId());

        Assert.noNullElements(new Object[]{payInfoMap,payInfoMap.get("pay_info"),payInfoMap.get("status")},
                ResultUtils.buildErrorMsg(ApiStatusEnum.SERVICE_ERR, ApiStatusEnum.SERVICE_ERR.getInfo()));

        String payInfo = payInfoMap.get("pay_info").toString();
        ModelAndView modelAndView = createModelAndView("/pay/wap_script");
        modelAndView.addObject("pay_info", payInfo);
        return modelAndView;
    }

    /**
     * 先excutor请求通道方，返回一个表单，再次提交表单
     * @param request
     * @param tradeNo
     * @return
     * @throws Exception
     */
    @RequestMapping(value = "/formAgain", method = RequestMethod.GET)
    private ModelAndView formAgain(
            HttpServletRequest request,
            @RequestParam("tradeNo") String tradeNo
    ) throws Exception {
        Assert.notNull(tradeNo, "请输入订单号");
        Order order = orderService.getByTradeNo(tradeNo);
        Assert.notNull(order, "订单号错误");
        Assert.isTrue(order.getState() == OrderStateEnum.NOTPAY.getType() ||
                order.getState() == OrderStateEnum.WAITING.getType(), "订单重复或者已支付");

        String pay_info = order.getAttach();
        ModelAndView modelAndView = createModelAndView("/pay/wap_script");
        modelAndView.addObject("pay_info", pay_info);
        return modelAndView;
    }

    /**
     * 上游返回二维码内容，需要生成二维码
     */
    @RequestMapping(value = "/createQrCode", method = RequestMethod.GET)
    private ModelAndView payOrder(
            HttpServletRequest request,
            @RequestParam("tradeNo") String tradeNo
    ) throws Exception {
        Assert.notNull(tradeNo, "请输入订单号");
        Order order = orderService.getByTradeNo(tradeNo);
        Assert.notNull(order, "订单号错误");
        Assert.isTrue(order.getState() == OrderStateEnum.NOTPAY.getType() ||
                order.getState() == OrderStateEnum.WAITING.getType(), "订单重复或者已支付");

        String pay_url = order.getAttach();
        ModelAndView modelAndView = null;
        if(order.getChannelType()<20){
            modelAndView = createModelAndView("/pay/wx_script");
        }else {
            modelAndView = createModelAndView("/pay/ali_script");
        }

        modelAndView.addObject("pay_url", pay_url);
        modelAndView.addObject("tradeNo", tradeNo);
        modelAndView.addObject("money", new BigDecimal(order.getAmount()).divide(new BigDecimal("100"), 2, BigDecimal.ROUND_DOWN).toString());
        return modelAndView;
    }

    @RequestMapping(value = "/toTestApi", method = RequestMethod.GET)
    public ModelAndView toTestApi() throws Exception {
        ModelAndView view = createModelAndView("/pay/test_api");
        List<ChannelType> channelTypes = channelTypeService.selectAll();
        view.addObject("channelTypes",channelTypes);
        return view;
    }
    /**
     * 测试接口
     *    //如果是扫码直接跳转二维码页面，如果是wap，直接返回提示+链接
     * status:0=wap成功，1等于失败
     */
    @RequestMapping(value = "/testApi", method = RequestMethod.POST)
    public ModelAndView testApi(
            HttpServletRequest request,
            @RequestParam("spId") Integer spId,
            @RequestParam("type") Integer type,
            @RequestParam(name = "money", required = false, defaultValue = "") String money,
            HttpServletResponse response
    ) throws Exception {
        ModelAndView view = createModelAndView("/pay/test_result");
        Assert.notNull(spId, "请输入spId");
        Assert.notNull(type, "请输入测试接口类型");
        Map<String, Object> params = new HashMap<>();
        params.put("out_trade_no", "test" +System.currentTimeMillis());
        params.put("total_fee", "".equals(money) ? "15" :
                new BigDecimal(money).multiply(new BigDecimal("100")).intValue());
        params.put("body", "test");
        params.put("mch_id", mchId);
        params.put("notify_url", "none");
        params.put("version", "1");
        params.put("mch_create_ip", "112.5.206.45");
        params.put("trade_type", type);

        params.put("sp_id", spId);

        Map<String, Object> result = null;
        try{
            CpPayAlipayWapRequest bean = (CpPayAlipayWapRequest) XmlUtils.mapToBean(
                    params, CpPayAlipayWapRequest.class);
            bean.setCpSecretId(secret);
            result = fourPayService.testCreateOrder(bean);
        }catch (Exception e){
            String message = e.getMessage();
            view.addObject("status","1");
            view.addObject("message",message==null?"系统抛出异常，请联系技术":message);
        }
        if(result!=null){
            if(ApiStatusEnum.OK.getCode().equals(result.get("status"))){
                String pay_info = result.get("pay_info").toString();
                if(pay_info.indexOf("http")==-1){
                    pay_info = request.getRequestURL().toString().split("api")[0]+pay_info;
                }
                //调用接口成功，先判断是扫码还是wap
                ChannelType channelType = channelTypeService.findById(type);
                if(channelType.getRateAdvance().intValue()>0){//0--扫码，1--wap
                    view.addObject("status","0");
                    view.addObject("redirect_url",pay_info);
                }else {
                    response.sendRedirect(pay_info);
                    return null;
                }

            }else {
                //调用接口失败
                view.addObject("status","1");
                view.addObject("message",result.get("message"));
            }
        }
        return view;
    }


    /**
     * 同步回调页面
     * @return
     * @throws Exception
     */
    @RequestMapping(value = "/sync", method = RequestMethod.GET)
    private ModelAndView sync(){
        ModelAndView modelAndView = new ModelAndView("/pay/success");
        return modelAndView;
    }
    /**
     * 同步错误页面
     * @return
     * @throws Exception
     */
    @RequestMapping(value = "/fail", method = RequestMethod.GET)
    private ModelAndView fail(){
        ModelAndView modelAndView = new ModelAndView("/pay/fail");
        return modelAndView;
    }
}
